//@author A0083402R
package userInterface;

import global.Constant;
import global.GlobalFields;
import global.Methods;

import java.awt.EventQueue;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.JTextArea;
import javax.swing.plaf.basic.BasicBorders;
import javax.swing.table.TableCellRenderer;

import storage.Storage;
import logic.ExecutionHandler;
import myTable.AttributiveCellRenderer;
import myTable.AttributiveCellTableModel;
import myTable.CellAttribute;
import myTable.CellFont;
import myTable.CellSpan;
import myTable.MultiSpanCellTable;

import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.RoundRectangle2D;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.ComponentOrientation;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;

import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;

public class GraphicalUI extends JFrame implements HotkeyListener {

	private static final int MINIMIZE = 0;
	private static final int ACTIVATE = 1;
	private MultiSpanCellTable showFeedback;
	private CellAttribute cellAttribute;
	private JTextField enterCommand;
	private JTextArea showSuggestion;
	private ImageIcon imageLogo;
	private ImageIcon imageHeader;
	private ArrayList<String> feedbackArr;
	private ArrayList<String> sectionHeadings;
	private ArrayList<Integer> pagingInfo;
	private String suggestionString;
	private String commandStr;
	private int maximumPage;
	private int currentPage;
	private boolean isCommandRead;
	private boolean justOpened;
	private boolean isHotKeyApplicable = true;
	private boolean isDisconnectMsgShown;
	
	public static void main(String[] args) {               

		Storage.init();
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					GraphicalUI mainFrame = new GraphicalUI();
					mainFrame.execute();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public GraphicalUI() {
		try {
			if (JIntellitype.checkInstanceAlreadyRunning("JIntellitype Test Application"))
				System.exit(1);
			if (!JIntellitype.isJIntellitypeSupported())
				System.exit(1);
		} catch (Exception e) {
			e.printStackTrace();
			isHotKeyApplicable = false;
		}

		initialize();

		if (isHotKeyApplicable) {
			initJIntellitype();
		}

		setTitle("BeautyRoxy Task Manager");
		center(this);        
		setVisible(true);
	}

	private void initialize() {
		
		isDisconnectMsgShown = false;
		imageLogo = new ImageIcon();
		imageHeader = new ImageIcon();

		Color backgroundColor = new Color(0x3C74C4);
		Color foregroundColor = new Color(0xEAEAEA);

		initMainFrame(backgroundColor);
		initHeader(backgroundColor, foregroundColor);
		initShowFeedback(backgroundColor, foregroundColor);
		initLogo(foregroundColor);
		initEnterCommand();
		initEnterCommandBackground(foregroundColor);
		initShowSuggestion(backgroundColor, foregroundColor);

		justOpened = true;
		isCommandRead = true;
		commandStr = "display today";

		maximumPage = 1;
		currentPage = 1;
		pagingInfo = new ArrayList<Integer>();

		setIconImage(imageLogo.getImage());
		setIconImage(imageHeader.getImage());
	}

	 private void initMainFrame(Color backgroundColor) {
		 Shape windowShape = new RoundRectangle2D.Double(0,0,450,600,20,40);
		 setUndecorated(true);
		 setOpacity(0.92f);
		 setShape(windowShape);
		 setResizable(false);
		 setFont(new Font("Calibri", Font.PLAIN, 13));
		 setTitle("BeautyRoxy Task Manager");

		 getContentPane().setBackground(backgroundColor);
		 getContentPane().setLayout(null);
		 setBounds(100, 100, 450, 630);
		 setFocusable(true);

		 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	 }

	 private void initHeader(Color backgroundColor, Color foregroundColor){
		 JLabel header = new JLabel();
		 header.setOpaque(true);
		 header.setBackground(backgroundColor);
		 header.setHorizontalAlignment(SwingConstants.LEFT);
		 imageHeader = new ImageIcon(GraphicalUI.class.getResource("headerlogo.png"));
		 header.setIcon(imageHeader);
		 header.setSize(420, 40);
		 header.setBounds(10, 10, 430, 50);
		 header.setBorder(new BasicBorders.MenuBarBorder(foregroundColor, Color.white));
		
		 getContentPane().add(header);	 
	 }

	private void initShowFeedback(Color backgroundColor, Color foregroundColor) {
		 AttributiveCellTableModel tableModel = new AttributiveCellTableModel(16, 4);
		 showFeedback = new MultiSpanCellTable(tableModel) {
	
			 @Override
			 public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
				 JLabel c = (JLabel) super.prepareRenderer(renderer, row, col);
				 if (row == 0 && col == 0) 
					 c.setHorizontalAlignment(JLabel.LEFT);
				 if (row != 0 && col == 0)
					 c.setHorizontalAlignment(JLabel.CENTER);
				 if (row != 0 && col != 0) 
					 c.setHorizontalAlignment(JLabel.LEFT);
				 if (col == 2)
					 c.setHorizontalAlignment(JLabel.RIGHT);
	
				 if (showFeedback.getValueAt(row, col) != null) {
					 if (!canTaskNameFit(showFeedback.getValueAt(row, col).toString(), 12))
						 c.setToolTipText(showFeedback.getValueAt(row, col).toString());
				 }
				 else 
					 c.setToolTipText(null);
			    
				 return c;
			 }
		 };
		 
		 showFeedback.setRowSelectionAllowed(false);
		 showFeedback.setColumnSelectionAllowed(false);
		 showFeedback.setCellSelectionEnabled(false);
		 showFeedback.setAutoCreateColumnsFromModel(false);
		 showFeedback.setBounds(10, 62, 430, 370);
		 showFeedback.setOpaque(false);
		 cellAttribute = tableModel.getCellAttribute();
		 showFeedback.setBackground(backgroundColor);
		 showFeedback.setShowVerticalLines(false);
		 showFeedback.setShowHorizontalLines(false);
		 showFeedback.setShowGrid(false);
		 showFeedback.setGridColor(backgroundColor);
		 showFeedback.setForeground(foregroundColor);
		 showFeedback.setFont(new Font("Calibri", Font.BOLD, 15));
		 showFeedback.setDefaultRenderer(Object.class, new AttributiveCellRenderer());
		 showFeedback.setRowHeight(22);
		 showFeedback.setColumnWidth(0, 62);
		 showFeedback.setColumnWidth(1, 233);
		 showFeedback.setColumnWidth(2, 123);
		 showFeedback.setColumnWidth(3, 12);
		 showFeedback.setEnabled(false);
		 
		 getContentPane().add(showFeedback);
	 }

	private void initLogo(Color foregroundColor) {
		 JLabel logo = new JLabel();
		 logo.setOpaque(true);
		 logo.setBackground(foregroundColor);
		 logo.setToolTipText("BeautyRoxy Task Manager");
		 logo.setEnabled(true);
		 logo.setHorizontalAlignment(SwingConstants.CENTER);
		 imageLogo = new ImageIcon(GraphicalUI.class.getResource("logo.png"));
		 logo.setIcon(imageLogo);
		 logo.setBounds(10, 430, 98, 67);

		 getContentPane().add(logo);
	 }

	 private void initEnterCommandBackground(Color foregroundColor) {
		 JLabel enterCommandBackground = new JLabel();
		 enterCommandBackground.setOpaque(true);
		 enterCommandBackground.setBackground(foregroundColor);
		 enterCommandBackground.setBounds(10, 430, 430, 67);

		 getContentPane().add(enterCommandBackground);
	 }

	 private void initEnterCommand() {
		 JTextField enterCommand = new JTextField("");
		 enterCommand.setOpaque(false);
		 enterCommand.setFont(new Font("Constantia", Font.PLAIN, 18));
		 enterCommand.setToolTipText("Enter command here");
		 enterCommand.setBorder(null);
		 enterCommand.setMargin(new Insets(0, 5, 0, 5));
		 enterCommand.setPreferredSize(new Dimension(14, 45));
		 enterCommand.setHorizontalAlignment(SwingConstants.LEFT);
		 enterCommand.setBounds(120, 430, 315, 67);
		 enterCommand.setColumns(10);
		 enterCommand.requestFocus();
		 
		 setEnterCommand(enterCommand);
		 getContentPane().add(getEnterCommand());

		 getEnterCommand().addActionListener(new ActionListener() {
			 public void actionPerformed(ActionEvent e) {
				 commandStr = getEnterCommand().getText();
				 isCommandRead = true;           
			 }
		 });
		 
		 Action goLeft = new AbstractAction() {
			 public void actionPerformed(ActionEvent actionEvent) {
				 if (currentPage > 0){
					 currentPage--;
					 setFeedback(currentPage);
				 }
			 } 
		 };
		 
		 Action goRight = new AbstractAction() {
			 public void actionPerformed(ActionEvent actionEvent) {
				 if (currentPage < maximumPage){
					 currentPage++;
					 setFeedback(currentPage);
				 }
			 } 
		 };
		 
		 KeyStroke leftkey = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.CTRL_MASK);
		 getEnterCommand().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(leftkey, "LEFT");
		 getEnterCommand().getActionMap().put("LEFT", goLeft);
		 
		 KeyStroke rightkey = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.CTRL_MASK);
		 getEnterCommand().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(rightkey, "RIGHT");
		 getEnterCommand().getActionMap().put("RIGHT", goRight);
		 
	 }

	 private void initShowSuggestion(Color backgroundColor, Color foregroundColor) {
		 showSuggestion = new JTextArea();
		 showSuggestion.setOpaque(true);
		 showSuggestion.setBackground(backgroundColor);
		 showSuggestion.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
		 showSuggestion.setBorder(null);
		 showSuggestion.setForeground(foregroundColor);
		 showSuggestion.setMargin(new Insets(10, 10, 10, 10));
		 showSuggestion.setLineWrap(true);
		 showSuggestion.setWrapStyleWord(true);
		 showSuggestion.setEditable(false);
		 showSuggestion.setFont(new Font("Calibri", Font.BOLD, 15));
		 showSuggestion.setBounds(10, 525, 430, 75);

		 getContentPane().add(showSuggestion);
	 }

	 public JTextField getEnterCommand() {
		 return enterCommand;
	 }

	public void setEnterCommand(JTextField enterCommand) {
		 this.enterCommand = enterCommand;
	 }

	public void clearTable() {

		 for (int i = 0; i < 4; i++)
			 for (int j = 0; j < 16; j++) {
				 showFeedback.setValueAt("", j, i);
				 ((CellSpan) cellAttribute).split(j, i);
			 }

		 int[] row = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
		 int[] col = {0, 1, 2, 3};
		 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 15), row, col);
	 }
	 
	 private void resetPaging() {
		 pagingInfo = new ArrayList<Integer>();
		 sectionHeadings = new ArrayList<String>();
	
		if (feedbackArr != null && feedbackArr.size()>0 ){
			pagingInfo.add(0);
			 int index = 0;
			 int maxIndex = feedbackArr.size()-1;
			 int counter = 0;
			 while (index < maxIndex) {
				 index = getFeedbackIndex(index);        
				 index++;
				 pagingInfo.add(index);
				 counter++;
				 maxIndex = feedbackArr.size()-1;
			 }
			 if (counter == 0){
				 pagingInfo.add(maxIndex);
				 sectionHeadings.add(feedbackArr.get(0));
			 }       
			 maximumPage = pagingInfo.size()-2;
			 currentPage = 0;
			 setFeedback(0);
		}
		 
	 }

	private int getFeedbackIndex(int startIndex) {
		 int rowNum = 0;
		 int index = startIndex;
		 boolean isNewHeadingRequired = false;
	
		 for (int i = startIndex; i < feedbackArr.size(); i++) {
			 String feedbackType = Methods.getFirstWord(feedbackArr.get(i));
			 
			 if (feedbackType.equalsIgnoreCase("heading")) {
				 if (rowNum > 0)
					 break;
				 else {
					 sectionHeadings.add(feedbackArr.get(i));
					 feedbackArr.remove(i);
					 i--;
					 isNewHeadingRequired = true;
				 }
			 } else if (feedbackType.equalsIgnoreCase("date")) {
				 if (rowNum > 7)
					 break;
				 else
					 rowNum++;
			 } else if (feedbackType.equalsIgnoreCase("muldate"))
				 rowNum++;
			 else if (feedbackType.equalsIgnoreCase("index"))
				 rowNum += 2;
	
			 if (rowNum < 11)
				 index = i;
			 else
				 break;           
		 }
	
		 if (!isNewHeadingRequired) {
			 String oldHeading = sectionHeadings.get(sectionHeadings.size()-1);
			 sectionHeadings.add(oldHeading);
		 }
	
		 return index;
	 }

	private boolean canTaskNameFit(String taskName, int fontSize) {
		 FontMetrics fm = getFontMetrics(new Font("Calibri", Font.BOLD, fontSize));
		 if (fm.stringWidth(taskName) < 350)
			 return true;
		 else
			 return false;
	 }

	 private void setFeedback(int pageNum){
		 if (pageNum >= 0 && pageNum <= maximumPage){
			 clearTable();
			 int startIndex = pagingInfo.get(pageNum);
			 int endIndex = pagingInfo.get(pageNum+1);
			 int rightRowNum = 2;
			 int leftRowNum = 0;

			 int[] pageRow = {0};
			 int[] pageCol = {2,3};
			 ((CellSpan) cellAttribute).combine(pageRow, pageCol);
			 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 22), 0, 2);
			 showFeedback.setValueAt("Page: (" + (pageNum+1) + "/" + (maximumPage+1) + ")", 0, 2);
			 
			 String heading = Methods.removeFirstWord(sectionHeadings.get(pageNum));
			 int[] headingRow = {0};
			 int[] headingCol = {0,1};

			 ((CellSpan) cellAttribute).combine(headingRow, headingCol);
			 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 22), headingRow, headingCol);
			 showFeedback.setValueAt(heading, 0, 0);

			 for (int k = startIndex; k < endIndex; k++) { 
				 leftRowNum = k - startIndex + 2;
				 String feedbackType = Methods.getFirstWord(feedbackArr.get(k));
				 String currentFeedback = Methods.removeFirstWord(feedbackArr.get(k));
				 
				 if (feedbackType.equalsIgnoreCase("date")) {
					 
					 int[] dateRow = {leftRowNum};
					 int[] dateCol = {0,1,2,3};

					 ((CellSpan) cellAttribute).combine(dateRow, dateCol);
					 showFeedback.setValueAt(currentFeedback, leftRowNum, 0);
					 rightRowNum++;
				 }
				 else if (feedbackType.equalsIgnoreCase("muldate")) {
					 int[] mulDateRow = {leftRowNum};
					 int[] mulDateCol = {1,2};

					 ((CellSpan) cellAttribute).combine(mulDateRow, mulDateCol);
					 showFeedback.setValueAt(currentFeedback, leftRowNum, 1);
					 rightRowNum++;
				 }
				 else if (feedbackType.equalsIgnoreCase("index")) {

					 int[] indexRow = {leftRowNum, leftRowNum+1};
					 int[] indexCol = {0};

					 ((CellSpan) cellAttribute).combine(indexRow, indexCol);
					 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 32), indexRow, indexCol);
					 showFeedback.setValueAt(currentFeedback, leftRowNum, 0);
					 rightRowNum++;
				 }

				 else if (feedbackType.equalsIgnoreCase("taskname")) {
					 int[] tasknameRow = {rightRowNum - 1};
					 int[] tasknameCol = {1,2};

					 ((CellSpan) cellAttribute).combine(tasknameRow, tasknameCol);
					 
					 if (!canTaskNameFit(currentFeedback, 18) && canTaskNameFit(currentFeedback, 17))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 17), tasknameRow, tasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 17) && canTaskNameFit(currentFeedback, 16))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 16), tasknameRow, tasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 16) && canTaskNameFit(currentFeedback, 15))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 15), tasknameRow, tasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 15) && canTaskNameFit(currentFeedback, 14))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 14), tasknameRow, tasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 14) && canTaskNameFit(currentFeedback, 13))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 13), tasknameRow, tasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 13) && canTaskNameFit(currentFeedback, 12))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 12), tasknameRow, tasknameCol);
					 else
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 18), tasknameRow, tasknameCol);
			
					 
					 showFeedback.setValueAt(currentFeedback, rightRowNum - 1, 1);
					 rightRowNum++;
				 }
				 
				 else if (feedbackType.equalsIgnoreCase("floattaskname")) {
					 int[] floatTasknameRow = {rightRowNum - 1, rightRowNum};
					 int[] floatTasknameCol = {1,2};

					 ((CellSpan) cellAttribute).combine(floatTasknameRow, floatTasknameCol);
					 
					 if (!canTaskNameFit(currentFeedback, 18) && canTaskNameFit(currentFeedback, 17))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 17), floatTasknameRow, floatTasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 17) && canTaskNameFit(currentFeedback, 16))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 16), floatTasknameRow, floatTasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 16) && canTaskNameFit(currentFeedback, 15))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 15), floatTasknameRow, floatTasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 15) && canTaskNameFit(currentFeedback, 14))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 14), floatTasknameRow, floatTasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 14) && canTaskNameFit(currentFeedback, 13))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 13), floatTasknameRow, floatTasknameCol);
					 else if (!canTaskNameFit(currentFeedback, 13) && canTaskNameFit(currentFeedback, 12))
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 12), floatTasknameRow, floatTasknameCol);
					 else
						 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 18), floatTasknameRow, floatTasknameCol);


					 showFeedback.setValueAt(currentFeedback, rightRowNum - 1, 1);
					 rightRowNum+=2;
				 }

				 else if (feedbackType.equalsIgnoreCase("time")) {
					 ((CellFont) cellAttribute).setFont(new Font("Calibri", Font.BOLD, 12), rightRowNum - 1, 1);
					 showFeedback.setValueAt(currentFeedback, rightRowNum - 1, 1);
					 rightRowNum++;
				 }                               
			 }
		 }
	 }

	 public void execute() {
		 if(GlobalFields.IS_GOOGLE_CONNECTED){
			 isDisconnectMsgShown = false;
		 }

		 if(!GlobalFields.IS_GOOGLE_CONNECTED && !isDisconnectMsgShown){
			 suggestionString += Constant.GOOGLE_DISCONNECTED_MESSAGE;
			 isDisconnectMsgShown = true;
			 showSuggestion.setText(suggestionString);
		 }

		 if (isCommandRead == true) {
			 if (commandStr.equalsIgnoreCase(Constant.EMPTY_STRING)) {
				 getEnterCommand().setVisible(true);
			 } else {
				 getEnterCommand().setText(Constant.EMPTY_STRING);
				 String commandString = Constant.EMPTY_STRING;
				 if (commandStr.equalsIgnoreCase("next")){
					 if (currentPage < maximumPage){
						 currentPage ++;
						 setFeedback(currentPage);
					 }
				 } else if (commandStr.equalsIgnoreCase("prev") || commandStr.equalsIgnoreCase("previous")){
					 if (currentPage > 0){
						 currentPage --;
						 setFeedback(currentPage);
					 }
				 } else if (Methods.getFirstWord(commandStr).equalsIgnoreCase("page")){
					 int targetPageNum = Methods.safeParseInt(Methods.removeFirstWord(commandStr))-1;
					 if (targetPageNum>=0 && targetPageNum<=maximumPage){
						 currentPage = targetPageNum;
						 setFeedback(currentPage);
					 }
				 } 
				 else {
					 commandString = commandStr;
					 try {
						 feedbackArr = ExecutionHandler.executeCommand(commandString);
						 int lastIndex = feedbackArr.size()-1;
						 if (justOpened){
							 suggestionString = "Welcome to BeautyRoxy Task Manager!\nToday's tasks are displayed by default.";
							 justOpened = false;
						 } else {
							 if(lastIndex >=0){
								 suggestionString = feedbackArr.get(lastIndex); 
							 } else {
								 suggestionString = "An unknown error has occur, please try again";
							 }
							 
						 }

						 if(lastIndex >=0){
							 feedbackArr.remove(lastIndex); 
						 } 
						
						 if (feedbackArr.size() == 0){
							 feedbackArr.add("HEADING  No result is found.");
						 }
					 } catch (Exception e1) {
						 suggestionString = e1.toString();                                             
					 }
					 resetPaging();
					 showSuggestion.setText(suggestionString);
				 }                               
			 }
			 isCommandRead = false;
		 }
	 }
//@Lim Wei Ke A0083402R
	 
	 private static void center(JFrame aFrame) {
		 final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		 final Point centerPoint = ge.getCenterPoint();
		 final Rectangle bounds = ge.getMaximumWindowBounds();
		 final int w = Math.min(aFrame.getWidth(), bounds.width);
		 final int h = Math.min(aFrame.getHeight(), bounds.height);
		 final int x = centerPoint.x - (w / 2);
		 final int y = centerPoint.y - (h / 2);
		 aFrame.setBounds(x, y, w, h);
		 if ((w == bounds.width) && (h == bounds.height)) {
			 aFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
		 }
		 aFrame.validate();
	 }

	 private void output(String text) {
		 showSuggestion.append(text);
		 showSuggestion.append("\n");
	 }

	 public void initJIntellitype() {
		 try {
			 // initialize JIntellitype with the frame so all windows commands can
			 // be attached to this window
			 addWindowListener(new java.awt.event.WindowAdapter() {
				 @Override
				 public void windowClosing(java.awt.event.WindowEvent evt) {
					 // don't forget to clean up any resources before close
					 JIntellitype.getInstance().cleanUp();
					 System.exit(0);
				 }
			 }); 

			 JIntellitype.getInstance().addHotKeyListener(this);
			 registerHotkey();
		 } catch (RuntimeException ex) {
			 output("Either you are not on Windows, or there is a problem with the JIntellitype library!");
		 }
	 }

	 private void registerHotkey() {
		 // assign the WINDOWS+A key to the unique id 88 for identification
		 JIntellitype.getInstance().registerHotKey(MINIMIZE, JIntellitype.MOD_ALT, 'M');
		 JIntellitype.getInstance().registerHotKey(ACTIVATE, JIntellitype.MOD_ALT, 'A');
	 }

	 public void onHotKey(int identifier) {
		 if (identifier == MINIMIZE){
			 this.setVisible(false);
		 } else if(identifier == ACTIVATE){
			 this.setVisible(true);
			 getEnterCommand().requestFocus();
		 }
	 }
}
